/*
*    Qizx/open 3.0 beta
*
* This code is the open-source version of Qizx.
* Copyright (C) 2004-2009 Axyana Software -- All rights reserved.
*
* The contents of this file are subject to the Mozilla Public License 
*  Version 1.1 (the "License"); you may not use this file except in 
*  compliance with the License. You may obtain a copy of the License at
*  http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
*  for the specific language governing rights and limitations under the
*  License.
*
* The Initial Developer of the Original Code is Xavier Franc - Axyana Software.
*
*/
using System;
using QizxException = System.Qizx.Api.QizxException;
using EvalContext = System.Qizx.XQuery.EvalContext;
using Focus = System.Qizx.XQuery.Focus;
using Function = System.Qizx.XQuery.Fn.Function;
namespace System.Qizx.XQuery.Op
{
	
	/// <summary> Superclass of all comparison operators.</summary>
	public abstract class Comparison:Expression
	{
		public Expression[] operands;
		
		public Comparison(Expression expr1, Expression expr2)
		{
			operands = new Expression[]{expr1, expr2};
		}
		
		public interface Test
		{
			string Name
			{
				get;
				
			}
			// diff is -1 if lt, 0 if eq, 1 if gt, or COMPARE_FAILS or INCOMPARABLE
			bool make(int diff);
			
			Comparison.Test reverse();
		}
		
		protected internal abstract Comparison.Test getTest();
		
		public override Expression Child(int rank)
		{
			return rank < 2?operands[rank]:null;
		}
		
		public abstract class Exec:Function.BoolCall
		{
			virtual public bool Eq
			{
				get
				{
					return test == ValueEqOp.TEST;
				}
				
			}
			public Comparison.Test test;
		}
		
		public virtual bool evalAsEffectiveBoolean(Focus focus, EvalContext context)
		{
			return evalAsBoolean(focus, context);
        }

        #region copy
        /// <summary>  Returned by method compareTo to say "less than".</summary>
        public const int LT = -1;

        /// <summary>  Returned by method compareTo when the two values are </summary>
        public const int GT = 1;

        /// <summary>  Returned by method compareTo when the two values are equal.</summary>
        public const int EQ = 0;

        /// <summary>  Returned by compare methods when the two values are not comparable.
        /// (generates an error)
        /// </summary>
        public const int ERROR = 2;

        /// <summary>  Returned by method compareTo when the test must fail 
        /// whatever the values (meant for NaN).
        /// </summary>
        public const int FAIL = 3;


        public static int of(int v1, int v2)
        {
            return v1 < v2 ? LT : (v1 > v2 ? GT : EQ);
        }

        public static int of(long v1, long v2)
        {
            return v1 < v2 ? LT : (v1 > v2 ? GT : EQ);
        }

        public static int of(double v1, double v2)
        {
            return v1 < v2 ? LT : (v1 > v2 ? GT : EQ);
        }

        // Used in sorts
        public static int of(double d1, double d2, bool emptyGreatest)
        {
            if (d1 != d1)
                //  NaN
                return emptyGreatest ? GT : LT;
            if (d2 != d2)
                return emptyGreatest ? LT : GT;
            // no NaN:
            return of(d1, d2);
        }
        #endregion
    }
}